#include "D3DRemoteProcessCaptor.h"
#include "D3DCaptor.h"
#include <tchar.h>

#define RETIFFAIL(r) if(!r) return FALSE;

BOOL CRemoteFunctionCreateCaptor::Execute(RPB_CreateCaptor& remoteCaptorParam)
{
	RPB_CreateCaptor* prpbR = (RPB_CreateCaptor*)VirtualAllocEx(*m_prm->GetRemoteProcess(), NULL, 
		sizeof(remoteCaptorParam), MEM_COMMIT, PAGE_READWRITE);
	if(prpbR)
	{
		WriteProcessMemory(*m_prm->GetRemoteProcess(), prpbR, &remoteCaptorParam, sizeof(remoteCaptorParam), NULL);
		DWORD dwExec = CRemoteFunction::Execute(prpbR);
		ReadProcessMemory(*m_prm->GetRemoteProcess(), prpbR, &remoteCaptorParam, sizeof(remoteCaptorParam), NULL);
		VirtualFreeEx(*m_prm->GetRemoteProcess(), prpbR, 0, MEM_RELEASE);

		return (dwExec == TRUE);
	}

	return FALSE;
}

//////////////////////////////////////////////////////////////////////
BOOL CD3DRemoteProcessCaptor::Create()
{
/*	if (!m_rp.Create(_T("wmplayer.exe"), 
		PROCESS_CREATE_THREAD | 
		PROCESS_QUERY_INFORMATION | 
		PROCESS_VM_OPERATION | 
		PROCESS_VM_WRITE | 
		PROCESS_VM_READ | 
		PROCESS_DUP_HANDLE))
		return FALSE;

	if (!m_rp.Create(_T("iexplore.exe"), 
		PROCESS_CREATE_THREAD | 
		PROCESS_QUERY_INFORMATION | 
		PROCESS_VM_OPERATION | 
		PROCESS_VM_WRITE | 
		PROCESS_VM_READ | 
		PROCESS_DUP_HANDLE))
		return FALSE;

	if (!m_rp.Create(_T("plugin-container.exe"), 
		PROCESS_CREATE_THREAD | 
		PROCESS_QUERY_INFORMATION | 
		PROCESS_VM_OPERATION | 
		PROCESS_VM_WRITE | 
		PROCESS_VM_READ | 
		PROCESS_DUP_HANDLE))
		return FALSE;

	if (!m_rp.Create(_T("chrome.exe"), 
		PROCESS_CREATE_THREAD | 
		PROCESS_QUERY_INFORMATION | 
		PROCESS_VM_OPERATION | 
		PROCESS_VM_WRITE | 
		PROCESS_VM_READ | 
		PROCESS_DUP_HANDLE))
		return FALSE;*/

	if (!m_rp.Create(_T("dwm.exe"), 
		PROCESS_CREATE_THREAD | 
		PROCESS_QUERY_INFORMATION | 
		PROCESS_VM_OPERATION | 
		PROCESS_VM_WRITE | 
		PROCESS_VM_READ | 
		PROCESS_DUP_HANDLE))
		return FALSE;

	TCHAR szName[MAX_PATH + 1];
	*szName = 0;
	GetModuleFileName(NULL, szName, sizeof(szName) /sizeof(szName[0]));
	TCHAR* p = _tcsrchr(szName, '\\');
	p = p ? p + 1 : szName;
	_tcscpy_s(p, MAX_PATH+1 - (p-szName), HD3D_LIBRARY);

	HMODULE hm = m_rm.FindProcessModule(m_rp, HD3D_LIBRARY);
	if(hm)
	{
		RETIFFAIL(m_rm.Create(szName, NULL, hm));
		RETIFFAIL(m_rfFin.Create(&m_rm, "RTFinalize"));
		m_rfFin.Execute(NULL);
		m_rm.Destroy();
	}

	RETIFFAIL(m_rm.Create(szName, NULL, NULL));
	RETIFFAIL(m_rfInit.Create(&m_rm, "RTInitialize"));
	RETIFFAIL(m_rfFin.Create(&m_rm, "RTFinalize"));
	RETIFFAIL(m_rfDestroy.Create(&m_rm,"RTDestroyCaptor"));

	return m_rfInit.Execute(NULL);
}

void CD3DRemoteProcessCaptor::Destroy()
{
	list<CD3DCaptor*>::iterator it;
	for (it = m_lstCaptors.begin(); it != m_lstCaptors.end(); it++)
	{
		delete *it;
	}
	m_lstCaptors.clear();
	m_rfFin.Execute(NULL);
	m_rm.Destroy();
	m_rp.Destroy();
}

BOOL CD3DRemoteProcessCaptor::CreateRemoteCaptor(RPB_CreateCaptor& remoteCaptorParam)
{
	if (m_rfCreate.Create("RTCreateCaptor"))
		return m_rfCreate.Execute(remoteCaptorParam);
	else
		return FALSE;
}

BOOL CD3DRemoteProcessCaptor::DestroyRemoteCaptor(HCAPTOR hCaptor)
{
	return m_rfDestroy.Execute(hCaptor);
}

CD3DCaptor* CD3DRemoteProcessCaptor::CreateCaptor(LPCSTR szDeviceName)
{
	CD3DCaptor* pcpt= new CD3DCaptor(this);
	if (!pcpt)
		return NULL;

	if (!pcpt->Create(szDeviceName))
	{
		delete pcpt;
		return NULL;
	}

	m_lstCaptors.push_back(pcpt);
	return pcpt;
}

BOOL CD3DRemoteProcessCaptor::DestroyCaptor(CD3DCaptor* pCaptor)
{
	m_lstCaptors.remove(pCaptor);
	delete pCaptor;
	return TRUE;
}